package org.arch_learn.servlet_container.components;

import org.arch_learn.servlet_container.components.container.Context;
import org.arch_learn.servlet_container.components.container.Host;
import org.arch_learn.servlet_container.components.container.Wrapper;
import org.arch_learn.servlet_container.pojo.CustomHttpServletRequest;

import javax.servlet.Servlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;

public class Mapper {

    public static HttpServlet getMappedServlet(Service service, HttpServletRequest request) {
        CustomHttpServletRequest cus = (CustomHttpServletRequest) request;

        String servletPath = cus.getServletPath();
        String contextPath = request.getContextPath();
        String host = request.getHeader("Host");

        AtomicReference<Servlet> matchedHttpServlet = new AtomicReference<>();

        Optional<Map.Entry<String, Host>> hostPortMatched = service
                .getEngine()
                .getHosts()
                .entrySet()
                .stream()
                .filter(stringHostEntry -> {
                    String hostWithOutPort = stringHostEntry.getKey();
                    String s = host.split(":")[0];
                    return s.equals(hostWithOutPort);
                }).findFirst();

        if (hostPortMatched.isPresent()) {
            Host hostInstance = hostPortMatched.get().getValue();
            Map<String, Context> contextMap = hostInstance.getContexts();
            Context context = contextMap.get(contextPath);
            if (context == null) return null;
            List<Wrapper> wrappers = context.getWrappers();

            wrappers.stream()
                    .filter(w -> w.getPattern().matcher(servletPath).matches())
                    .findFirst()
                    .ifPresent(v -> matchedHttpServlet.set(v.getServlet()));
        }
        return (HttpServlet)matchedHttpServlet.get();
    }

    public static String getMappedStaticResources(Service service, HttpServletRequest httpServletRequest) {
        CustomHttpServletRequest cus = (CustomHttpServletRequest) httpServletRequest;

        String servletPath = cus.getServletPath();
        servletPath = servletPath.contains(".") ? "" : servletPath;
        String contextPath = httpServletRequest.getContextPath();
        String host = httpServletRequest.getHeader("Host");

        AtomicReference<String> mappedStaticResourcesUrl = new AtomicReference<>();
        mappedStaticResourcesUrl.set("/");

        Optional<Map.Entry<String, Host>> hostPortMatched = service.getEngine()
                .getHosts()
                .entrySet()
                .stream()
                .filter(stringHostEntry -> {
                    String hostWithOutPort = stringHostEntry.getKey();
                    String s = host.split(":")[0];
                    return s.equals(hostWithOutPort);
                }).findFirst();

        if (hostPortMatched.isPresent()) {
            Host hostInstance = hostPortMatched.get().getValue();
            String appBase = hostInstance.getAppBase();
            String fileName = httpServletRequest.getRequestURI()
                    .replace(contextPath, "")
                    .replace(servletPath, "");
            String fileFullPath = appBase + fileName;
            mappedStaticResourcesUrl.set(fileFullPath);
        }
        return mappedStaticResourcesUrl.get();
    }
}
